079 |
您所在的位置:网站首页 › 条件竞争 测试工具包括 › 079 |
大多数时候,我们对并发的直觉都是错误的,特别是在多核处理器上更为明显。这也是高并发程序难写的原因。 人类想了种种办法来降低程序员犯错误的机率,发明了很多方法。甚至在有些语言里,干脆就不支持多线程了,比如基于 NodeJs 开发的服务器。 但在 Golang 里我们无法逃避这种并发竞争。 1. 竞争例子下面这个例子开启了 100 个 goroutine,读写全局变量 a. // demo01.go package main import ( "fmt" "sync" ) var a int func run() { a++ } func main() { var wg sync.WaitGroup num := 100 wg.Add(num) for i := 0; i < num; i++ { go func() { run() wg.Done() }() } wg.Wait() fmt.Printf("a = %d\n", a) }上面的程序反复运行了几次,发现有几次结果不太一样,我们期望的结果应该是 100。 原因就在于 a++ 这一行语句不是原子执行的。 2. 竞争检测golang 提供了竞争检测工具,用来辅助我们发现程序种出现的数据竞争。只要在命令后面加上 -race 选项就可以了: $ go test -race mypkg // 测试包 $ go run -race mysrc.go // 编译和运行程序 $ go build -race mycmd // 构建程序 $ go install -race mypkg // 安装程序在我们这个例子中,你可以使用下面的方法: $ go run -race demo01.go或者你也可以使用 $ go build -race demo01.go $ ./demo01竞争检测器集成在go工具链中。当使用了-race作为命令行参数后,编译器会插桩代码,使得所有代码在访问内存时,会记录访问时间和方法。同时运行时库会观察对共享变量的未同步访问。 3. 使用互斥锁解决竞争问题 // demo02.go package main import ( "fmt" "sync" ) var a int var mu sync.Mutex func run() { mu.Lock() defer mu.Unlock() a++ } func main() { var wg sync.WaitGroup num := 100 wg.Add(num) for i := 0; i < num; i++ { go func() { run() wg.Done() }() } wg.Wait() fmt.Printf("a = %d\n", a) }接下来再运行 go run -race demo02.go,就没有问题了,而且每次结果都是 100. |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |